/*
 * Copyright (C) 2009 Jakub Miara
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.araim.rringtone;

import java.util.HashMap;
import java.util.TreeSet;

import com.araim.BackgroundColorAnimation;
import com.araim.rringtone.db.RandomRingtoneDatabase;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.CompoundButton.OnCheckedChangeListener;

/**
 * @author Jakub Miara
 * @version 1.0
 * 
 *          This is an Activity allowing user to select any number of ringtones
 *          from the ringtone list read from the device Upon clicking save it
 *          returns the array of selected ringtones
 */
public class SelectRingtonesActivity extends Activity {

	/**
	 * an internal holder for selected ringtone information
	 */
	private HashMap<String, RingtoneInfo> tones = new HashMap<String, RingtoneInfo>();
	/**
	 * the name of a key under which the array of selected ringtones is stored
	 */
	public static final String SAVED_RINGTONES_LIST = "SAVED_RINGTONES_LIST";

	public static final String RINGTONE_TYPE = "RINGTONE_TYPE";

	public static final int REQUEST_BROWSE = 1;

	private LinearLayout innerLayout = null;
	private ProgressDialog pd = null;
	private int type;

	private Handler ringtonesLoadedhandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			try {
				LinearLayout llayout = (LinearLayout) findViewById(R.id.SelectRingtoneMainLayout);
				llayout.addView(innerLayout);
			} catch (Exception e) {
				Log.e(RandomRingtone.TAG, "Error displaying ringtones");
				Toast.makeText(getApplicationContext(), R.string.toast_cant_fetch, 1000);
			} finally {
				pd.dismiss();
			}
		}
	};

	private class PrepareUI implements Runnable {
		private Bundle bundle;

		public PrepareUI(Bundle b) {
			bundle = b;
		}

		public void run() {
			try {
				if (bundle != null) {
					RingtoneInfo[] list = (RingtoneInfo[]) bundle.getParcelableArray(SAVED_RINGTONES_LIST);
					if (list != null) {
						for (RingtoneInfo info : list) {
							tones.put(info.getFullUri(), info);
						}
					}
					// or from the database (if this is opening the activity
					// anew)
				} else {
					RandomRingtoneDatabase rrd = new RandomRingtoneDatabase(getApplicationContext());
					for (RingtoneInfo info : rrd.getAllRingtones(type)) {
						tones.put(info.getFullUri(), info);
					}
				}

				innerLayout = new LinearLayout(getApplicationContext());
				innerLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
				innerLayout.setOrientation(LinearLayout.VERTICAL);

				Button browse = (Button) findViewById(R.id.AddRingtone);

				browse.setOnClickListener(new OnClickListener() {

					public void onClick(View v) {
						Intent i = new Intent(getApplicationContext(), com.araim.rringtone.BrowseForRingtones.class);
						i.putExtra(RINGTONE_TYPE, type);
						startActivityForResult(i, REQUEST_BROWSE);
					}
				});

				RingtoneManager rm = new RingtoneManager(SelectRingtonesActivity.this);
				rm.setType(type);
				RingtoneSelectionListener rsl = new RingtoneSelectionListener();

				Cursor c = rm.getCursor();
				// for each ringtone returned by ringtone manager

				TreeSet<RingtoneInfo> ts = new TreeSet<RingtoneInfo>();
				while (c.moveToNext()) {
					// create Ringtone info object
					RingtoneInfo ri = new RingtoneInfo();
					ri.setId(c.getInt(RingtoneManager.ID_COLUMN_INDEX));
					ri.setName(c.getString(RingtoneManager.TITLE_COLUMN_INDEX));
					ri.setUri(c.getString(RingtoneManager.URI_COLUMN_INDEX));
					ri.setRtype(type);
					ts.add(ri);
				}
				for (RingtoneInfo ri : ts) {
					View v = LayoutInflater.from(getApplicationContext()).inflate(R.layout.ringtonelistitem, null);
					RelativeLayout ll = (RelativeLayout) v.findViewById(R.id.FileContainer);
					CheckBox cb = (CheckBox) ll.findViewById(R.id.RingtoneCheckbox);

					new BackgroundColorAnimation(ll, android.R.color.background_dark, 0xfff36900, 500, new View[] { cb });

					ImageButton iv = (ImageButton) ll.findViewById(R.id.RingtoneDeleteButton);
					iv.setTag(ri);
					iv.setOnClickListener(new OnClickListener() {

						public void onClick(View v) {
							final RingtoneInfo ri = (RingtoneInfo) v.getTag();
							final View view = v;
							final String typeName = type == RingtoneManager.TYPE_RINGTONE ? "ringtone" : "notification";
							new AlertDialog.Builder(SelectRingtonesActivity.this)

							.setTitle("Remove Ringtone").setMessage(
									"Do you want to remove this " + typeName
											+ "?\nNOTE: The file itself will not be removed, just marked as not a " + typeName + ".")
									.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
										public void onClick(DialogInterface dialog, int which) {
											if (tones.containsKey(ri.getFullUri())) {
												tones.remove(ri.getFullUri());
											}
											((LinearLayout) view.getParent().getParent().getParent()).removeView((View) view.getParent()
													.getParent());
											RingtoneInfo.disable(getContentResolver(), Uri.parse(ri.getUri()), ri.getId(), type);
											Toast.makeText(getApplicationContext(),
													String.format(typeName + " \"%s\" removed.", ri.getName()), 1000).show();
										}
									}).setNegativeButton("No", null).show();
						}
					});

					// CheckBox(getApplicationContext());
					cb.setWidth(android.view.ViewGroup.LayoutParams.FILL_PARENT);
					cb.setHeight(android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
					cb.setText(ri.getName());

					// store the object as a tag for the checkbox
					cb.setTag(ri);

					// if the id of this ringtone is in our temp list,
					// pre-select it
					if (tones.containsKey(ri.getFullUri())) {
						cb.setChecked(true);
					}

					cb.setOnCheckedChangeListener(rsl);

					// add the checkbox to view

					innerLayout.addView(v);
				}

				Message m = new Message();
				ringtonesLoadedhandler.sendMessage(m);

			} catch (Exception e) {
				Log.e(RandomRingtone.TAG, "Error displaying ringtones: " + e.toString());
			}
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		try {
			setContentView(R.layout.selectringtoneslayout);
			type = getIntent().getIntExtra(RINGTONE_TYPE, -1);
			if (type == -1) {
				Log.e(RandomRingtone.TAG, "Ringtone type not present. ");
				return;
			}

			Button save = (Button) findViewById(R.id.ButtonSave);
			Button cancel = (Button) findViewById(R.id.ButtonCancel);

			cancel.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					try {
						SelectRingtonesActivity.this.setResult(RESULT_CANCELED);
						finish();
					} catch (Exception e) {
						Log.e(RandomRingtone.TAG, "Error on canceling: " + e.toString());
					}
				}
			});

			// Saving the ringtones (returning from activity)
			save.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					try {
						Bundle b = new Bundle();
						b.putParcelableArray(SAVED_RINGTONES_LIST, tones.values().toArray(new RingtoneInfo[0]));
						b.putInt(RINGTONE_TYPE, type);
						Intent mIntent = new Intent();
						mIntent.putExtras(b);
						SelectRingtonesActivity.this.setResult(RESULT_OK, mIntent);
						finish();
					} catch (Exception e) {
						Log.e(RandomRingtone.TAG, "Error on returning selection result: " + e.toString());
					}
				}
			});

			if (type == RingtoneManager.TYPE_RINGTONE) {
				pd = ProgressDialog.show(this, "Please Wait", "Fetching rintones list", true, true);
			} else {
				pd = ProgressDialog.show(this, "Please Wait", "Fetching notifications list", true, true);
			}
			PrepareUI p = new PrepareUI(savedInstanceState);
			Thread t = new Thread(p);
			t.start();

		} catch (Exception e) {
			Log.e(RandomRingtone.TAG, "Error initializing ringtone selection: " + e.toString());
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (data != null) {
			Parcelable[] added = data.getParcelableArrayExtra(BrowseForRingtones.ADDED_RINGTONES);
			if (added != null) {
				for (Parcelable p : added) {
					RingtoneInfo ri = (RingtoneInfo) p;
					tones.put(ri.getFullUri(), ri);
				}
			}
		}
		Bundle b = new Bundle();
		onSaveInstanceState(b);
		onCreate(b);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			try {
				Bundle b = new Bundle();
				b.putParcelableArray(SAVED_RINGTONES_LIST, tones.values().toArray(new RingtoneInfo[0]));
				b.putInt(RINGTONE_TYPE, type);
				Intent mIntent = new Intent();
				mIntent.putExtras(b);
				SelectRingtonesActivity.this.setResult(RESULT_OK, mIntent);
				finish();
			} catch (Exception e) {
				Log.e(RandomRingtone.TAG, "Error on returning selection result: " + e.toString());
			}
		}
		return true;
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		try {
			// get the list of selected ringtones
			RingtoneInfo[] rings = tones.values().toArray(new RingtoneInfo[0]);
			// save it as an array in the bundle
			outState.putParcelableArray(SAVED_RINGTONES_LIST, rings);
		} catch (Exception e) {
			Log.e(RandomRingtone.TAG, "Error saving instance state: " + e.toString());
		}
	}

	private class RingtoneSelectionListener implements OnCheckedChangeListener {

		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			try {
				// get the ringtone info of related to this checkbox
				// from
				// it's tag
				RingtoneInfo ri = (RingtoneInfo) ((CheckBox) buttonView).getTag();

				if (isChecked) {
					tones.put(ri.getFullUri(), ri);
				} else {
					tones.remove(ri.getFullUri());
				}

			} catch (Exception e) {
				Log.e(RandomRingtone.TAG, "Error selecting ringtone: " + e.toString());
			}

		}

	}
}
